FrameLib  0.7
DSP processing with frames of arbitrary timing and length
FrameLib_Threading.h
Go to the documentation of this file.
1 
2 #ifndef FrameLib_THREADING_H
3 #define FrameLib_THREADING_H
4 
5 #ifdef __APPLE__
6 
7 #include <libkern/OSAtomic.h>
8 #include <pthread.h>
9 #include <mach/semaphore.h>
10 #include <mach/task.h>
11 
12 namespace OS_Specific
13 {
14  // Mac OS specific definitions
15 
16  typedef volatile int32_t Atomic32;
17 
18  static inline int32_t increment32(Atomic32 *a) { return OSAtomicIncrement32Barrier(a); }
19  static inline int32_t decrement32(Atomic32 *a) { return OSAtomicDecrement32Barrier(a); }
20  static inline int32_t add32(Atomic32 *a, int32_t b) { return OSAtomicAdd32Barrier(b, a); }
21  static inline bool compareAndSwap32(Atomic32 *loc, int32_t comp, int32_t exch) { return OSAtomicCompareAndSwap32Barrier(comp, exch, loc); }
22 
23  typedef void * volatile AtomicPtr;
24 
25  static inline bool compareAndSwapPtr(AtomicPtr *loc, void *comp, void *exch) { return OSAtomicCompareAndSwapPtrBarrier(comp, exch, loc); }
26  static inline void *swapPtr(AtomicPtr *loc, void *swap)
27  {
28  void *ptr = *loc;
29 
30  while (!compareAndSwapPtr(loc, ptr, swap))
31  ptr = *loc;
32 
33  return ptr;
34  }
35 
36  typedef pthread_t OSThreadType;
37  typedef semaphore_t OSSemaphoreType;
38  typedef void *OSThreadFunctionType(void *arg);
39 }
40 
41 #else
42 
43  // Windows OS specific definitions
44 
45 #include <windows.h>
46 
47 namespace OS_Specific
48 {
49  typedef volatile long Atomic32;
50 
51  static inline long increment32(Atomic32 *a) { return InterlockedIncrement(a); }
52  static inline long decrement32(Atomic32 *a) { return InterlockedDecrement(a); }
53  static inline long add32(Atomic32 *a, long b) { return InterlockedAdd(a, b); }
54  static inline bool compareAndSwap32(Atomic32 *loc, long comp, long exch) { return InterlockedCompareExchange(loc, exch, comp) == comp; }
55 
56  typedef volatile PVOID AtomicPtr;
57 
58  static inline bool compareAndSwapPtr(AtomicPtr *loc, void *comp, void *exch) { return InterlockedCompareExchangePointer(loc, exch, comp) == comp; }
59  static inline void *swapPtr(AtomicPtr *loc, void *swap) { return InterlockedExchangePointer(loc, swap); }
60 
61  typedef HANDLE OSThreadType;
62  typedef HANDLE OSSemaphoreType;
63  typedef DWORD WINAPI OSThreadFunctionType(LPVOID arg);
64 }
65 
66 #endif
67 
68 // An atomic 32 bit integer
69 
70 class Atomic32
71 {
72 
73 public:
74 
75  Atomic32(int32_t value) : mValue(value) {}
76  Atomic32() : mValue(0) {}
77 
78  bool compareAndSwap(int32_t comparand, int32_t exchange) { return OS_Specific::compareAndSwap32(&mValue, comparand, exchange); }
79 
80  int32_t operator = (const int32_t value)
81  {
82  mValue = value;
83  return value;
84  }
85 
86  int32_t operator += (const int32_t& a) { return OS_Specific::add32(&mValue, a); }
87 
88  int32_t operator ++ () { return OS_Specific::increment32(&mValue); }
89  int32_t operator ++ (int) { return operator++() - 1; }
90  int32_t operator -- () { return OS_Specific::decrement32(&mValue); }
91  int32_t operator -- (int) { return operator--() + 1; }
92 
93 private:
94 
95  // Deleted
96 
97  Atomic32(const Atomic32&);
98  Atomic32& operator=(const Atomic32&);
99 
100  OS_Specific::Atomic32 mValue;
101 };
102 
103 
104 // An atomic pointer
105 
106 template <class T> class AtomicPtr
107 {
108 
109 public:
110 
111  AtomicPtr() { mValue = NULL; }
112 
113  bool compareAndSwap(T *comparand, T *exchange) { return OS_Specific::compareAndSwapPtr(&mValue, comparand, exchange); }
114  T *swap(T *exchange) { return (T *) OS_Specific::swapPtr(&mValue, exchange); }
115  T *clear() { return swap(NULL); }
116 
117 private:
118 
119  // Deleted
120 
121  AtomicPtr(const AtomicPtr&);
122  AtomicPtr& operator=(const AtomicPtr&);
123 
124  OS_Specific::AtomicPtr mValue;
125 };
126 
127 
128 // A spinlock that can be locked, attempted or acquired
129 
130 class SpinLock
131 {
132 
133 public:
134 
135  SpinLock() {}
136  ~SpinLock() { acquire(); }
137 
138  bool attempt() { return mAtomicLock.compareAndSwap(0, 1); }
139  void acquire() { while(attempt() == false); }
140  void release() { mAtomicLock.compareAndSwap(1, 0); }
141 
142 private:
143 
144  // Deleted
145 
146  SpinLock(const SpinLock&);
147  SpinLock& operator=(const SpinLock&);
148 
149  Atomic32 mAtomicLock;
150 };
151 
152 
153 // A class for holding a lock using RAII
154 
156 {
157 
158 public:
159 
160  SpinLockHolder(SpinLock *lock) : mLock(lock) { if (mLock) mLock->acquire(); }
161  ~SpinLockHolder() { if (mLock) mLock->release(); }
162 
163  void destroy()
164  {
165  if (mLock)
166  mLock->release();
167  mLock = NULL;
168  }
169 
170 private:
171 
172  SpinLock *mLock;
173 };
174 
175 
176 // Lightweight joinable thread
177 
178 class Thread
179 {
180 
181  typedef void ThreadFunctionType(void *);
182 
183 public:
184 
185  enum PriorityLevel {kLowPriority, kMediumPriority, kHighPriority, kAudioPriority};
186 
187  Thread(PriorityLevel priority, ThreadFunctionType *threadFunction, void *arg)
188  : mInternal(NULL), mPriority(priority), mThreadFunction(threadFunction), mArg(arg), mValid(false)
189  {}
190 
191  ~Thread();
192 
193  void start();
194  void join();
195 
196 private:
197 
198  // Deleted
199 
200  Thread(const Thread&);
201  Thread& operator=(const Thread&);
202 
203  // threadStart is a quick OS-style wrapper to call the object which calls the relevant static function
204 
205  static OS_Specific::OSThreadFunctionType threadStart;
206  void call() { mThreadFunction(mArg); }
207 
208  // Data
209 
210  OS_Specific::OSThreadType mInternal;
211  PriorityLevel mPriority;
212  ThreadFunctionType *mThreadFunction;
213  void *mArg;
214  bool mValid;
215 };
216 
217 
218 // Semaphore (note that you should most likely close() before the destructor is called)
219 
221 {
222 
223 public:
224 
225  Semaphore(long maxCount);
226  ~Semaphore();
227 
228  void close();
229  void signal(long n);
230  bool wait();
231 
232 private:
233 
234  // Deleted
235 
236  Semaphore(const Semaphore&);
237  Semaphore& operator=(const Semaphore&);
238 
239  // Data
240 
242  bool mValid;
243 };
244 
245 
246 // A thread that can be triggered from another thread but without any built-in mechanism to check progress
247 
249 {
250 
251 public:
252 
253  TriggerableThread(Thread::PriorityLevel priority) : mThread(priority, threadEntry, this), mSemaphore(1) {}
254  virtual ~TriggerableThread() {}
255 
256  // Start and join
257 
258  void start() { mThread.start(); }
259  void join();
260 
261  // Trigger the thread to do something
262 
263  void signal() { mSemaphore.signal(1); };
264 
265 private:
266 
267  // Deleted
268 
269  TriggerableThread(const Thread&);
270  TriggerableThread& operator=(const Thread&);
271 
272  // threadEntry simply calls threadClassEntry which calls the task handler
273 
274  static void threadEntry(void *thread);
275  void threadClassEntry();
276 
277  // Override this and provide code for the thread's functionality
278 
279  virtual void doTask() = 0;
280 
281  // Data
282 
283  Thread mThread;
284  Semaphore mSemaphore;
285 };
286 
287 
288 // A thread to delegate tasks to, which can be then be checked for completion
289 
291 {
292 
293 public:
294 
295  DelegateThread(Thread::PriorityLevel priority) : mThread(priority, threadEntry, this), mSemaphore(1), mSignaled(false) {}
296  virtual ~DelegateThread() {}
297 
298  // Start and join
299 
300  void start() { mThread.start(); }
301  void join();
302 
303  // Signal the thread to do something if it is not busy (returns true if the thread was signalled, false if busy)
304 
305  bool signal();
306 
307  // Wait for thread's completion of a task - returns true first time after a signal / false for subsequent calls/the thread has not been signalled
308 
309  bool completed();
310 
311 private:
312 
313  // Deleted
314 
316  DelegateThread& operator=(const DelegateThread&);
317 
318  // threadEntry simply calls threadClassEntry which calls the task handler
319 
320  static void threadEntry(void *thread);
321  void threadClassEntry();
322 
323  // Override this and provide code for the thread's functionality
324 
325  virtual void doTask() = 0;
326 
327  // Data
328 
329  Thread mThread;
330  Semaphore mSemaphore;
331 
332  bool mSignaled;
333  Atomic32 mFlag;
334 };
335 
336 #endif
DWORD WINAPI OSThreadFunctionType(LPVOID arg)
Definition: FrameLib_Threading.h:63
T * clear()
Definition: FrameLib_Threading.h:115
Definition: FrameLib_Threading.h:130
bool attempt()
Definition: FrameLib_Threading.h:138
SpinLockHolder(SpinLock *lock)
Definition: FrameLib_Threading.h:160
void signal()
Definition: FrameLib_Threading.h:263
void start()
Definition: FrameLib_Threading.h:300
void start()
Definition: FrameLib_Threading.h:258
Atomic32()
Definition: FrameLib_Threading.h:76
Definition: FrameLib_Threading.h:178
TriggerableThread(Thread::PriorityLevel priority)
Definition: FrameLib_Threading.h:253
void release()
Definition: FrameLib_Threading.h:140
SpinLock()
Definition: FrameLib_Threading.h:135
virtual ~DelegateThread()
Definition: FrameLib_Threading.h:296
int32_t operator++(int)
Definition: FrameLib_Threading.h:89
~SpinLock()
Definition: FrameLib_Threading.h:136
void destroy()
Definition: FrameLib_Threading.h:163
~SpinLockHolder()
Definition: FrameLib_Threading.h:161
HANDLE OSSemaphoreType
Definition: FrameLib_Threading.h:62
Definition: FrameLib_Threading.h:290
HANDLE OSThreadType
Definition: FrameLib_Threading.h:61
Definition: FrameLib_Threading.h:248
Atomic32(int32_t value)
Definition: FrameLib_Threading.h:75
Definition: FrameLib_Threading.h:220
volatile PVOID AtomicPtr
Definition: FrameLib_Threading.h:56
Definition: FrameLib_Threading.h:47
virtual ~TriggerableThread()
Definition: FrameLib_Threading.h:254
bool compareAndSwap(int32_t comparand, int32_t exchange)
Definition: FrameLib_Threading.h:78
AtomicPtr()
Definition: FrameLib_Threading.h:111
int32_t operator--(int)
Definition: FrameLib_Threading.h:91
volatile long Atomic32
Definition: FrameLib_Threading.h:49
Thread(PriorityLevel priority, ThreadFunctionType *threadFunction, void *arg)
Definition: FrameLib_Threading.h:187
void start()
Definition: FrameLib_Threading.cpp:120
bool compareAndSwap(T *comparand, T *exchange)
Definition: FrameLib_Threading.h:113
DelegateThread(Thread::PriorityLevel priority)
Definition: FrameLib_Threading.h:295
T * swap(T *exchange)
Definition: FrameLib_Threading.h:114
PriorityLevel
Definition: FrameLib_Threading.h:185
Definition: FrameLib_Threading.h:155
void acquire()
Definition: FrameLib_Threading.h:139